package cn.com.surker.base.system.service.impl;

import cn.com.surker.base.system.dao.SysStorageDao;
import cn.com.surker.base.system.dao.SysStorageLineDao;
import cn.com.surker.base.system.dao.SysStorageLogDao;
import cn.com.surker.base.system.dao.SysStorageMatchDao;
import cn.com.surker.base.system.entity.SysStorage;
import cn.com.surker.base.system.entity.SysStorageLine;
import cn.com.surker.base.system.entity.SysStorageLog;
import cn.com.surker.base.system.entity.SysStorageMatch;
import cn.com.surker.base.system.service.SysStorageService;
import cn.com.surker.base.system.vo.SysStorageLineVo;
import cn.com.surker.base.system.vo.SysStorageVo;
import cn.com.surker.common.Constant;
import cn.com.surker.common.MessageCenterException;
import cn.com.surker.database.JDBCTemplateCache;
import cn.com.surker.dto.system.SysStorageDTO;
import cn.com.surker.dto.system.SysStorageMatchDTO;
import cn.com.surker.enums.base.StorageEnjoyTypeEnum;
import cn.com.surker.enums.base.StorageStoreTypeEnum;
import cn.com.surker.enums.material.MaterialInventoryEnum;
import cn.com.surker.enums.material.MaterialStoreTypeEnum;
import cn.com.surker.enums.material.StorageTypeEnum;
import cn.com.surker.enums.system.DataBaseEnum;
import cn.com.surker.enums.weight.OrderWeightTypeEnum;
import cn.com.surker.enums.weight.WeightCarTypeEnum;
import cn.com.surker.enums.weight.WeightTypeEnum;
import cn.com.surker.lab.dao.LabExpendDao;
import cn.com.surker.lab.dao.LabExpendOtherDao;
import cn.com.surker.material.dao.MainMaterialHistoryInventoryDao;
import cn.com.surker.material.dao.MainMaterialWeightDao;
import cn.com.surker.material.entity.MainMaterialHistoryInventory;
import cn.com.surker.material.entity.MainMaterialWeight;
import cn.com.surker.material.vo.MainMaterialWeightVo;
import cn.com.surker.material.vo.MaterialHistoryInventoryVo;
import cn.com.surker.redis.RedisUtils;
import cn.com.surker.spring.RestResultDto;
import cn.com.surker.system.dao.DataSourceInfoDao;
import cn.com.surker.system.entity.DataSourceInfo;
import cn.com.surker.system.model.CacheUser;
import cn.com.surker.util.DateUtil;
import cn.com.surker.util.StringUtils;
import cn.com.surker.vo.main.MainMaterialWeightVO;
import cn.com.surker.vo.system.SysStorageMatchVO;
import cn.com.surker.vo.system.SysStorageVO;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.snaker.engine.SnakerException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Slf4j
@Service
public class SysStorageServiceImpl implements SysStorageService {

    @Resource
    private SysStorageDao mapper;
    @Resource
    private SysStorageLineDao storageLineDao;
    @Resource
    private DataSourceInfoDao dsDao;
    @Resource
    private SysStorageLogDao sysStorageLogDao;
    @Resource
    private SysStorageMatchDao storageMatchDao;
    @Resource
    private MainMaterialWeightDao materialWeightDao;
    @Resource
    private RedisUtils redisUtils;
    @Resource
    private MainMaterialHistoryInventoryDao historyInventoryDao;
    @Resource
    private LabExpendDao expendDao;
    @Resource
    private LabExpendOtherDao expendOtherDao;

    /**
     * 根据公司、类型查询仓位信息
     * @param orgId
     * @param type 0:筒仓1:堆场
     * @return
     */
    public List<SysStorage> findByOrg(Long orgId, Integer type, Long materialId) {
        QueryWrapper<SysStorage> query = new QueryWrapper<>();
        query.eq("status", 0);
        if (!StringUtils.isNull(orgId))
            query.eq("org_id", orgId);
        if (!StringUtils.isNull(type))
            query.eq("type", type);
        if (!StringUtils.isNull(materialId))
            query.eq("material_id", materialId);
        query.orderByDesc("id");
        List<SysStorage> list = mapper.selectList(query);
        if (list == null || list.size() == 0)
            return null;
        return list;
    }

    /**
     *
     * 根据公司、类型查询云端仓位信息
     * @param orgId
     * @param type 0:筒仓1:堆场
     * @return
     */
    public List<SysStorage> findCloudByOrg(Long orgId, Long lineId, Integer type, Long materialId) {
        if (StringUtils.isNull(orgId))
            return null;
        DataSourceInfo ds = dsDao.queryDSByOriginIdV1(orgId, DataBaseEnum.MYSQL.getCode());
        if (ds == null || ds.getType() != 0)
            return null;
        List<SysStorage> list = mapper.findCloudByOrg(ds.getCode(), orgId, lineId, materialId, type);
        if (list == null || list.size() == 0)
            return null;
        return list;
    }
    /**
     *
     * 加载盘存明细仓位信息
     * @param orgId
     * @return
     */
    public List<SysStorageVo> findCloudOrgOrInventory(Long orgId, String today) {
        if (StringUtils.isNull(orgId))
            return null;
        DataSourceInfo ds = dsDao.queryDSByOriginIdV1(orgId, DataBaseEnum.MYSQL.getCode());
        if (ds == null || ds.getType() != 0)
            return null;

        List<SysStorageVo> list = mapper.findCloudOrgOrInventory(ds.getCode(), orgId, today);
        if (list == null || list.size() == 0)
            return null;
        return list;
    }

    @Override
    public IPage<SysStorageVO> page(SysStorageDTO dto) {
        PageHelper.offsetPage(dto.getOffsetSize(), dto.getLimit());
        Page<SysStorageVO> page = new Page<>(dto.getCurrSize(), dto.getLimit());
        IPage<SysStorageVO> iPage = mapper.page(page, dto);
        /**分页插件**/
        if (ObjectUtil.isNotEmpty(iPage)) {
            PageInfo pageInfo = new PageInfo(iPage.getRecords());
            if (!StringUtils.isNull(pageInfo.getTotal())) iPage.setTotal(pageInfo.getTotal());
        }
        return iPage;
    }

    /**
     * 云端分页方法
     * @param storage
     * @return
     */
    public IPage<SysStorageVo> cloudPage(SysStorageVo storage, Integer offset, Integer limit) {
        if (storage == null || StringUtils.isNull(storage.getOrgId()))
            return null;

        DataSourceInfo ds = dsDao.queryDSByOriginIdV1(storage.getOrgId(), DataBaseEnum.MYSQL.getCode());
        if (ds == null || ds.getType() != 0)
            return null;
        PageHelper.offsetPage(offset, limit);
        IPage<SysStorageVo> iPage = mapper.cloudPage(new Page<>((offset + limit) /limit, limit), ds.getCode(), storage);
        if (ObjectUtil.isNotEmpty(iPage)) {
            PageInfo pageInfo = new PageInfo(iPage.getRecords());
            if (!StringUtils.isNull(pageInfo.getTotal())) iPage.setTotal(pageInfo.getTotal());
        }
        return iPage;
    }

    /**
     * 更新关联信息
     * @param storage
     * @return
     */
    public RestResultDto updateStorageCloud(SysStorage storage) {
        if (StringUtils.isNull(storage) || StringUtils.isNull(storage.getId()))
            throw new MessageCenterException("参数错误");
        if (StringUtils.isNull(storage.getOrgId()))
            throw new MessageCenterException("更新公司信息为空");
        if (StringUtils.isNull(storage.getIsCloud()))
            throw new MessageCenterException("更新类型错误");
        if (StringUtils.isNull(storage.getCoefficient()) && StringUtils.isNull(storage.getStorageDesc())
                && StringUtils.isNull(storage.getRadius()))
            throw new MessageCenterException("设置参数错误");
        DataSourceInfo ds = dsDao.queryDSByOriginIdV1(storage.getOrgId(), DataBaseEnum.MYSQL.getCode());
        if (ds == null || ds.getType() != 0)
            throw new MessageCenterException("数据源信息错误");
        SysStorageVo sysStorageVo = mapper.selectCloudById(ds.getCode(), storage.getId());
        if (sysStorageVo == null)
            throw new MessageCenterException("仓位信息不存在");
        Date nowDate = new Date();
        storage.setUpdateTime(nowDate);
        Integer code = mapper.updateDescCloud(ds.getCode(), storage);
        if (code > 0) {
            String updateSql = "update " + ds.getCode() + ".sys_storage set updator ='" + storage.getUpdator() + "',update_time='"
                    + DateUtil.convertString(nowDate)+ "'";
            if (!StringUtils.isNull(storage.getRadius()))
                updateSql += ",radius = " + storage.getRadius();
            if (!StringUtils.isNull(storage.getCoefficient()))
                updateSql += ",coefficient = " + storage.getCoefficient();
            if (!StringUtils.isNull(storage.getStorageDesc()))
                updateSql += ",storage_desc = '" + storage.getStorageDesc() + "'";
            if (!StringUtils.isNull(storage.getRemark()))
                updateSql += ",remark = '" + storage.getRemark() + "'";
            updateSql += " where id = " + storage.getId() + " and org_id = " + storage.getOrgId();
            JdbcTemplate jdbcTemplate = JDBCTemplateCache.getLocalJdbcTemplate(ds);
            code = jdbcTemplate.update(updateSql);
            if (code > 0)
                return RestResultDto.success("更新成功~！");
        }
        return RestResultDto.fail("更新错误");
    }

    @Override
    public Boolean add(SysStorageDTO dto, CacheUser user) {
        SysStorage sysStorage = BeanUtil.copyProperties(dto, SysStorage.class);
        if (StringUtils.isAllParamNull(sysStorage.getMaterialId(), sysStorage.getMaterial()))
            throw new MessageCenterException("未选择材料信息");
        sysStorage.setStatus(0);
        sysStorage.setCreator(user.getName());
        sysStorage.setCreateTime(new Date());
        Integer code = mapper.insert(sysStorage);
        return code > 0;
    }

    @Override
    public RestResultDto edit(SysStorageDTO dto, CacheUser user) {
        if (ObjectUtil.isEmpty(dto.getId())) {
            throw new SnakerException("标识不存在，请检查数据！");
        }
        SysStorage sysStorage = mapper.selectById(dto.getId());
        if (ObjectUtil.isEmpty(sysStorage)) {
            throw new SnakerException("当前仓位信息不存在，请重新处理！");
        }
        Date nowDate = new Date();
        if (!StringUtils.isNull(dto.getName()) && !StringUtils.isNull(sysStorage.getName())
                && !dto.getName().equals(sysStorage.getName())) {
            SysStorageMatchDTO matchDTO = new SysStorageMatchDTO();
            matchDTO.setStorageId(dto.getId());
            matchDTO.setStatus(0);
            List<SysStorageMatchVO> matchVOList = storageMatchDao.page(matchDTO);
            if (matchVOList != null && matchVOList.size() > 0) {
                List<SysStorageLog> logList = new ArrayList<>();
                for (int i = 0; i < matchVOList.size(); i++) {
                    SysStorageMatchVO matchVO = matchVOList.get(i);
                    SysStorageLog storageLog = new SysStorageLog(sysStorage.getOrgId(), sysStorage.getId(), sysStorage.getName(),
                            dto.getName(), matchVO.getMaterialId(), matchVO.getMaterialName(),
                            matchVO.getLineId(), 0, nowDate, user.getName(), nowDate);
                    storageLog.setStatus(0);
                    logList.add(storageLog);
                }
                if (logList != null && logList.size() > 0) {
                    Integer code = sysStorageLogDao.saveBatch(logList);
                    if (code < 1)
                        throw new MessageCenterException("更新ERP仓位变更记录错误~！");
                }
            }
        }
        String saveTip = "";
        //存在材料修改
        if (!StringUtils.isNull(sysStorage.getMaterialId()) && !StringUtils.isNull(dto.getMaterialId())
                && sysStorage.getMaterialId().longValue() != dto.getMaterialId().longValue()) {
            List<SysStorageMatch> matchList = storageMatchDao.findByStorageId(sysStorage.getId());
            String takeTime = DateUtil.convertString(nowDate);
            if (!StringUtils.isNull(dto.getInventoryTime()))
                takeTime = DateUtil.convertString(dto.getInventoryTime());

            if (matchList != null && matchList.size() > 0) {
                if (sysStorage.getIsEnjoy().intValue() == 1) {
                    List<SysStorageLog> logList = new ArrayList<>();
                    for (int i = 0; i < matchList.size(); i++) {
                        SysStorageMatch matchVO = matchList.get(i);
                        SysStorageLog storageLog = new SysStorageLog(sysStorage.getOrgId(), sysStorage.getId(), sysStorage.getName(),
                                dto.getName(), dto.getMaterialId(), dto.getMaterial(),
                                matchVO.getLineId(), 0, nowDate, user.getName(), nowDate);
                        storageLog.setStatus(0);
                        logList.add(storageLog);
                    }
                    if (logList != null && logList.size() > 0) {
                        Integer code = sysStorageLogDao.saveBatch(logList);
                        if (code < 1)
                            throw new MessageCenterException("更新ERP仓位变更记录错误~！");
                        SysStorageMatch storageMatch = matchList.get(0);
                        MainMaterialHistoryInventory historyInventory = historyInventoryDao.findByStoreId(sysStorage.getId());
                        if (historyInventory == null) {
                            saveTip = "仓位:" + sysStorage.getName() + "\n材料:" + dto.getMaterial() + "\n期初值:0吨,购进值:0吨,消耗值:0吨,目前库存:0吨\n生效时间:" + takeTime;
                            historyInventory = new MainMaterialHistoryInventory(sysStorage.getOrgId(), dto.getMaterialId(),
                                    sysStorage.getId(), DateUtil.convertDate(takeTime), nowDate, 0.0, 0.0, 0.0,
                                    0.0, MaterialInventoryEnum.CWHL.getCode(), storageMatch.getControlId());
                        } else {
                            String startTime = DateUtil.convertString(historyInventory.getStartDate());
                            String endTime = DateUtil.convertString(nowDate);
                            //自动消耗
                            Double autoDosage = expendDao.findSumDosage(sysStorage.getId(), sysStorage.getMaterialId(), startTime, endTime);
                            //手动消耗
                            Double handDosage = expendOtherDao.findSumOtherDosage(sysStorage.getId(), sysStorage.getMaterialId(), startTime, endTime);
                            //购进总数
                            Double netWeight = materialWeightDao.findSumNetWeight(sysStorage.getId(), sysStorage.getMaterialId(),
                                    WeightCarTypeEnum.MATERIAL.getCode(), OrderWeightTypeEnum.YC.getCode(), startTime, endTime);
                            Double initial = historyInventory.getInitial() + historyInventory.getAdjustment() + netWeight - autoDosage - handDosage;
                            historyInventory.setCrease(netWeight);
                            historyInventory.setReduse(autoDosage + handDosage);
                            historyInventory.setCheckDate(DateUtil.convertDate(takeTime));
                            historyInventory.setUpdateTime(nowDate);
                            historyInventory.setUpdator(user.getName());
                            historyInventoryDao.updateById(historyInventory);//保存原有盘存数据
                            saveTip = "仓位:" + sysStorage.getName() + "\n材料:" + sysStorage.getMaterial() + "\n期初值:" + StringUtils.formatDouble(historyInventory.getInitial() / 1000, 2)
                                    + "吨,调整值:" + StringUtils.formatDouble(historyInventory.getAdjustment() / 1000, 2)
                                    + "吨,购进值:" + StringUtils.formatDouble(netWeight / 1000, 2)
                                    + "吨,消耗值:" + StringUtils.formatDouble((autoDosage + handDosage) / 1000, 2)
                                    + "吨,目前库存:" + StringUtils.formatDouble(initial / 1000, 2) + "吨\n生效时间:" + takeTime;

                            historyInventory.setMaterialId(dto.getMaterialId());
                            historyInventory.setId(null);
                            historyInventory.setCreator(user.getName());
                            historyInventory.setInitial(initial);
                            historyInventory.setAdjustment(0.0);
                            historyInventory.setCrease(0.0);
                            historyInventory.setReduse(0.0);
                            historyInventory.setStartDate(DateUtil.convertDate(takeTime));
                            historyInventory.setCheckDate(nowDate);
                            historyInventory.setStoreId(sysStorage.getId());
                            historyInventory.setControlStoreId(storageMatch.getControlId());
                        }
                        historyInventory.setCreateTime(nowDate);
                        historyInventory.setRemark(dto.getMaterial() + "仓位换料盘点记录材料ID:" + historyInventory.getMaterialId() + "-->" + dto.getMaterialId());
                        historyInventory.setMaterialId(dto.getMaterialId());
                        if (!StringUtils.isNull(historyInventory.getId()) && sysStorage.getIsEnjoy().intValue() == 1) {//如果不是共享仓
                            historyInventory.setId(null);
                            code = historyInventoryDao.insert(historyInventory);
                            if (code < 1)
                                throw new MessageCenterException("保存换料盘点记录错误");
                        } else {
                            code = historyInventoryDao.insert(historyInventory);
                            if (code < 1)
                                throw new MessageCenterException("保存换料盘点记录错误");
                        }
                    }
                    SysStorageMatch storageMatch = matchList.get(0);
                    storageMatch.setMaterialId(dto.getMaterialId());
                    storageMatch.setUpdateTime(nowDate);
                    storageMatch.setUpdator(user.getName());
                    storageMatch.setRemark("ERP仓位换料,更新材料信息[" + dto.getMaterial() + "]");
                    storageMatchDao.updateById(storageMatch);
                } else {
                    List<SysStorageLog> logList = new ArrayList<>();
                    Double initial = 0.0;
                    Double crease = 0.0;
                    Double reduse = 0.0;
                    for (int i = 0; i < matchList.size(); i++) {
                        SysStorageMatch matchVO = matchList.get(i);
                        SysStorageLog storageLog = new SysStorageLog(sysStorage.getOrgId(), sysStorage.getId(), sysStorage.getName(),
                                dto.getName(), dto.getMaterialId(), dto.getMaterial(),
                                matchVO.getLineId(), 0, nowDate, user.getName(), nowDate);
                        storageLog.setStatus(0);
                        logList.add(storageLog);
                        SysStorageMatch storageMatch = matchList.get(i);
                        MainMaterialHistoryInventory historyInventory = historyInventoryDao.findByStoreId(matchVO.getStorageId());
                        if (historyInventory == null) {
                            saveTip = "仓位:" + sysStorage.getName() + "\n材料:" + sysStorage.getMaterial() + "\n期初值:0吨,购进值:0吨,消耗值:0吨,目前库存:0吨\n生效时间:" + takeTime;
                            historyInventory = new MainMaterialHistoryInventory(sysStorage.getOrgId(), sysStorage.getMaterialId(),
                                    sysStorage.getId(), DateUtil.convertDate(takeTime), nowDate, 0.0, 0.0, 0.0,
                                    0.0, MaterialInventoryEnum.CWHL.getCode(), storageMatch.getControlId());
                        } else {
                            if (i == 0) {
                                String startTime = DateUtil.convertString(historyInventory.getStartDate());
                                String endTime = DateUtil.convertString(nowDate);
                                //自动消耗
                                Double autoDosage = expendDao.findSumDosage(sysStorage.getId(), sysStorage.getMaterialId(), startTime, endTime);
                                //手动消耗
                                Double handDosage = expendOtherDao.findSumOtherDosage(sysStorage.getId(), sysStorage.getMaterialId(), startTime, endTime);
                                //购进总数
                                Double netWeight = materialWeightDao.findSumNetWeight(sysStorage.getId(), sysStorage.getMaterialId(),
                                        WeightCarTypeEnum.MATERIAL.getCode(), OrderWeightTypeEnum.YC.getCode(), startTime, endTime);
                                initial = historyInventory.getInitial() + historyInventory.getAdjustment() + netWeight - autoDosage - handDosage;
                                crease = netWeight;
                                reduse = autoDosage + handDosage;
                                saveTip = "仓位:" + sysStorage.getName() + "\n材料:" + dto.getMaterial() + "\n期初值:" + StringUtils.formatDouble(historyInventory.getInitial() / 1000, 2)
                                        + "吨,调整值:" + StringUtils.formatDouble(historyInventory.getAdjustment() / 1000, 2)
                                        + "吨,购进值:" + StringUtils.formatDouble(crease / 1000, 2)
                                        + "吨,消耗值:" + StringUtils.formatDouble(reduse / 1000, 2)
                                        + "吨,目前库存:" + StringUtils.formatDouble(initial / 1000, 2) + "吨\n生效时间:" + takeTime;
                            }
                            historyInventory.setCrease(crease);
                            historyInventory.setReduse(reduse);
                            historyInventory.setCheckDate(DateUtil.convertDate(takeTime));
                            historyInventory.setUpdateTime(nowDate);
                            historyInventory.setUpdator(user.getName());
                            historyInventoryDao.updateById(historyInventory);//保存原有盘存数据

                            historyInventory.setMaterialId(dto.getMaterialId());
                            historyInventory.setId(null);
                            historyInventory.setCreator(user.getName());
                            historyInventory.setInitial(initial);
                            historyInventory.setAdjustment(0.0);
                            historyInventory.setCrease(0.0);
                            historyInventory.setReduse(0.0);
                            historyInventory.setStartDate(DateUtil.convertDate(takeTime));
                            historyInventory.setCheckDate(nowDate);
                            historyInventory.setStoreId(sysStorage.getId());
                            historyInventory.setControlStoreId(storageMatch.getControlId());
                        }
                        historyInventory.setCreateTime(nowDate);
                        historyInventory.setRemark(dto.getMaterial() + "仓位换料盘点记录材料ID:" + historyInventory.getMaterialId() + "-->" + dto.getMaterialId());
                        historyInventory.setMaterialId(dto.getMaterialId());
                        Integer code = historyInventoryDao.insert(historyInventory);
                        if (code < 1)
                            throw new MessageCenterException("保存换料盘点记录错误");
                        matchVO.setUpdateTime(nowDate);
                        matchVO.setUpdator(user.getName());
                        matchVO.setMaterialId(dto.getMaterialId());
                        matchVO.setRemark("ERP仓位换料更新" + matchVO.getMaterialId() + "--->" + dto.getMaterialId());
                        storageMatchDao.updateById(matchVO);

                    }
                    if (logList != null && logList.size() > 0) {
                        Integer code = sysStorageLogDao.saveBatch(logList);
                        if (code < 1)
                            throw new MessageCenterException("更新ERP仓位变更记录错误~！");

                    }
//                    for (int i = 0; i < matchList.size(); i++) {
//                        SysStorageMatch matchVO = matchList.get(i);
//                        matchVO.setStatus(1);
//                        matchVO.setUpdateTime(nowDate);
//                        matchVO.setUpdator(user.getName());
//                        matchVO.setRemark("ERP仓位换料,共享仓取消工控关联");
//                        storageMatchDao.updateById(matchVO);
//                    }
                }
            }
        }
        BeanUtil.copyProperties(dto, sysStorage);
        sysStorage.setUpdateTime(new Date());
        sysStorage.setUpdator(user.getName());
        mapper.updateById(sysStorage);
        if (!StringUtils.isNull(saveTip))
            return RestResultDto.success(saveTip);

        return RestResultDto.success("更新成功");
    }

    @Override
    public Boolean editStatus(Long id, Integer status, CacheUser user) {
        if (ObjectUtil.isEmpty(id)) {
            throw new SnakerException("标识不存在，请检查数据！");
        }
        SysStorage sysStorage = mapper.selectById(id);
        if (ObjectUtil.isEmpty(sysStorage)) {
            throw new SnakerException("当前仓位信息不存在，请重新处理！");
        }
        sysStorage.setStatus(status);
        sysStorage.setUpdateTime(new Date());
        sysStorage.setUpdator(user.getName());
        return mapper.updateById(sysStorage) > 0;
    }


    /**
     * 查询生产线关联信息
     * @param storageId
     * @return
     */
    public List<SysStorageLineVo> findStorageId(Long storageId) {
        if (StringUtils.isNull(storageId))
            throw new MessageCenterException("参数错误");
        List<SysStorageLineVo> lineVoList = storageLineDao.findStorageId(storageId);
        return lineVoList;
    }

    /**
     * 保存仓位与生产线关联信息
     * @param storageLine
     * @return
     */
    public RestResultDto saveStorageLine(SysStorageLine storageLine) {
        if (StringUtils.isNull(storageLine))
            throw new MessageCenterException("参数错误");
        if (StringUtils.isNull(storageLine.getLineId()))
            throw new MessageCenterException("生产线为空");
        if (StringUtils.isNull(storageLine.getStorageId()) || storageLine.getStorageId() < 1)
            throw new MessageCenterException("仓位信息为空");
        SysStorage storage = mapper.selectById(storageLine.getStorageId());
        if (storage == null || storage.getStatus() == 1)
            throw new MessageCenterException("仓位信息不存在或已被禁用");
        SysStorageLine storageLine1 = storageLineDao.findStorageOrLine(storageLine.getStorageId(),storageLine.getLineId());
        Date nowDate = new Date();
        if (storageLine1 != null) {
            storageLine1.setStatus(0);
            storageLine1.setUpdateTime(nowDate);
            storageLine1.setUpdator(storageLine.getCreator());
            Integer code = storageLineDao.updateById(storageLine1);
            if (code > 0)
                return RestResultDto.success("保存成功", storageLine1);
            else
                return RestResultDto.fail("保存失败");
        }
        if (storage.getIsEnjoy().intValue() == 1) {
            QueryWrapper<SysStorageLine> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("status", 0);
            queryWrapper.eq("storage_id", storageLine.getStorageId());
            Integer total = storageLineDao.selectCount(queryWrapper);
            if (total > 0)
                throw new MessageCenterException("非共享仓不能关联多条生产线,请选取消关联后再操作");
        }
        storageLine.setCreateTime(nowDate);
        storageLine.setStatus(0);
        Integer code = storageLineDao.insert(storageLine);
        if (code > 0)
            return RestResultDto.success("保存成功", storageLine);
        else
            return RestResultDto.fail("保存失败");
    }

    /**
     * 更新关联信息
     * @param storageLine
     * @return
     */
    public RestResultDto updateStorageLine(SysStorageLine storageLine) {
        if (StringUtils.isNull(storageLine) || StringUtils.isNull(storageLine.getId()))
            throw new MessageCenterException("参数错误");
        SysStorageLine storageLine1 = storageLineDao.selectById(storageLine.getId());
        if (storageLine1 == null)
            throw new MessageCenterException("仓位关联信息不存在");
        storageLine1.setStatus(storageLine.getStatus());
        storageLine1.setUpdator(storageLine.getUpdator());
        storageLine1.setUpdateTime(new Date());
        Integer code = storageLineDao.updateById(storageLine1);
        if (code > 0)
            return RestResultDto.success("更新成功", storageLine1);
        else
            return RestResultDto.fail("更新失败");
    }

	@Override
	public List<SysStorage> findByMaterial(Long materialId) {
		if (materialId == null) {
			return null;
		}
		List<SysStorage> storages = mapper.findByMaterial(materialId);
		return storages;
	}

    /**
     * 查询料仓详情，LED屏显示数据
     * @param dbCode
     * @param lineId
     * @param storageCode
     * @return
     */
    public Map<String, Object> findStorageDetail(String dbCode, Long lineId, String storageCode) {
        if (StringUtils.isAllParamNull(dbCode, lineId, storageCode))
            throw new MessageCenterException("参数错误");
        String key = Constant.REDIS_STORAGE_LINE_KEY + "_" + dbCode + "_" +lineId + "_" +storageCode;
        if (redisUtils.exists(key)) {
            Map<String, Object> storageMap = StringUtils.aliConvertMap(StringUtils.convertString(redisUtils.get(key)));
            return storageMap;
        }
        List<SysStorageVo> storageVoList = mapper.selectCloudByCode(dbCode, lineId, storageCode);
        if (storageVoList == null || storageVoList.size() == 0)
            throw new MessageCenterException("仓位信息不存在");
        SysStorageVo storageVo = storageVoList.get(0);
        Date nowDate = new Date();
        String nowTime = DateUtil.convertString(nowDate);
        Long storageId = storageVo.getId();
        MaterialHistoryInventoryVo inventoryVo = historyInventoryDao.findCloudByControlMaterial(dbCode, storageId, null, nowTime);
        if (inventoryVo == null || inventoryVo.getStatus() == 1)
            throw new MessageCenterException("仓位盘存信息不存在");
        Long materialId = inventoryVo.getMaterialId();
        String inventoryTime = DateUtil.convertString(inventoryVo.getStartDate());
        Double netWeight = materialWeightDao.findCloudSumNetWeight(dbCode, storageId,materialId,WeightCarTypeEnum.MATERIAL.getCode(),
                OrderWeightTypeEnum.YC.getCode(), inventoryTime, nowTime, null, null);
        Double dosage = expendDao.findCloudSumDosage(dbCode, storageId, materialId, inventoryTime, nowTime);
        Double otherDosage = expendOtherDao.findCloudSumOtherDosage(dbCode, storageId, materialId, inventoryTime, nowTime);
        netWeight = StringUtils.formatDouble(netWeight / 1000, 1);
        dosage = StringUtils.formatDouble(dosage / 1000, 1);
        otherDosage = StringUtils.formatDouble(otherDosage / 1000, 1);
        Double initStorage = StringUtils.formatDouble(StringUtils.convertDouble(inventoryVo.getInitial()) / 1000, 1);//期初值
        Double maxStorage = StringUtils.formatDouble(StringUtils.convertDouble(storageVo.getMaxCapacity()) / 1000,1);//最大容量
        if (maxStorage > 99999)
            maxStorage = 9999.0;
        QueryWrapper<MainMaterialWeight> weightQuery = new QueryWrapper<>();
        weightQuery.eq("a.storage_id", storageId);
        weightQuery.eq("a.material_id", materialId);
        weightQuery.eq("a.is_store", 0);
        weightQuery.ge("a.in_time", inventoryTime);
        weightQuery.eq("a.status", 0);
        weightQuery.eq("a.weight_type", OrderWeightTypeEnum.YC.getCode());
        weightQuery.eq("a.car_type", WeightCarTypeEnum.MATERIAL.getCode());
        weightQuery.orderByDesc("a.in_time");
        Double carNetWeight = 0.0;
        String storageStatus = "空闲";
        String carNo = "";
        String supplier = "";
        String storageTime = DateUtil.convertString(nowDate, "MMdd HH:mm");
        List<MainMaterialWeightVO> weightVOList = materialWeightDao.findCloudWeightPage(weightQuery, dbCode);
        if (weightVOList != null && weightVOList.size() > 0) {
            MainMaterialWeightVO materialWeightVO = weightVOList.get(0);
            carNo = materialWeightVO.getCarNo();
            if (!StringUtils.isNull(materialWeightVO.getSupplier()))
                supplier = materialWeightVO.getSupplier();
            if (!StringUtils.isNull(materialWeightVO.getInTime()))
                storageTime = DateUtil.convertString(materialWeightVO.getInTime(), "MMdd HH:mm");
            if (!StringUtils.isNull(materialWeightVO.getNetWeight())) {
                carNetWeight = StringUtils.formatDouble(StringUtils.convertDouble(materialWeightVO.getNetWeight())/ 1000, 1);
            } else {
                if (!StringUtils.isNull(materialWeightVO.getInTime())) {
                    Date inTime = materialWeightVO.getInTime();
                    Integer time = DateUtil.differentMins(nowDate, inTime);
                    if (time < 1440)
                        storageStatus = "上料中";
                }
                carNetWeight = StringUtils.formatDouble(StringUtils.convertDouble(materialWeightVO.getSupplierNetWeight())/ 1000, 1);
            }
        }
        Double storageValue = StringUtils.formatDouble(initStorage + netWeight - dosage - otherDosage, 1);

        Map<String, Object> map = new HashMap<>();
        map.put("storageCode", storageVo.getCode());//仓位信息
        map.put("storageValue", storageValue);//库存
        map.put("maxStorage", maxStorage);//最大容量
        map.put("carNetWeight", carNetWeight);//车辆净重
        map.put("storageId", storageId);//仓位ID
        map.put("supplier", supplier);//供应商
        map.put("carNo", carNo);//车牌
        map.put("material", inventoryVo.getMaterialNorms());//材料
        map.put("storageStatus", storageStatus);//仓位状态
        map.put("storageTime", storageTime);//进场时间
        redisUtils.set(key, StringUtils.convertJSONObject(map), 60l);
        return map;
    }
    /**
     * 实时库存
     * @param time
     * @return
     */
    public Map<String, List<SysStorageVo>> realTimeStore(String time, String dbCode) {
        if (StringUtils.isNull(dbCode))
            throw new MessageCenterException("站点参数错误");
        if (StringUtils.isNull(time))
            time = DateUtil.convertString(new Date());
        /**非共享仓**/
        List<SysStorageVo> unEnjoyList = mapper.findStoreLastTime(dbCode, time, StorageEnjoyTypeEnum.FGX.getCode());
        /**共享仓**/
        List<SysStorageVo> enjoyList = mapper.findStoreLastTimeV1(dbCode, time, StorageEnjoyTypeEnum.GX.getCode());

        Map<String, List<SysStorageVo>> resultMap = convertUnEnjoy(unEnjoyList);//非共享仓
        if (resultMap == null)
            resultMap = new LinkedHashMap<>();
        resultMap.put("共享仓", convertEnjoy(enjoyList, MaterialStoreTypeEnum.TC.getCode()));
        resultMap.put("堆仓", convertEnjoy(enjoyList, MaterialStoreTypeEnum.DC.getCode()));

        resultMap.put("筒仓明细", unEnjoyList);
        resultMap.put("共享仓明细", convertEnjoyDetail(enjoyList, MaterialStoreTypeEnum.TC.getCode()));
        resultMap.put("堆仓明细", convertEnjoyDetail(enjoyList, MaterialStoreTypeEnum.DC.getCode()));
        return resultMap;
    }
    @Override
    public List<SysStorage> findByMaterial(DataSourceInfo ds, Long materialId) {
        if (ds == null || materialId == null) {
            return null;
        }
        JdbcTemplate jdbcTemplate = JDBCTemplateCache.getLocalJdbcTemplate(ds);
        String querySql = "SELECT a.id, a.org_id, a.code, a.name, a.type, a.is_enjoy, a.is_store,a.max_capacity, a.inventory_time, a.status, a.remark, a.creator, a.create_time, a.updator, a.update_time,a.material_id\n" +
                "from sys_storage a\n" +
                "where a.status = 0 and a.material_id = ? GROUP BY a.id";
        Object[] params = {materialId};
        List<SysStorage> query = jdbcTemplate.query(querySql, params, BeanPropertyRowMapper.newInstance(SysStorage.class));
        return query;
    }

    /**
     * 转换非共享仓
     * @return
     */
    private Map<String, List<SysStorageVo>> convertUnEnjoy(List<SysStorageVo> list) {
        if (list == null)
            return null;
        Map<String, List<SysStorageVo>> map = new LinkedHashMap<>();
        for (int i = 0; i < list.size(); i++) {
            SysStorageVo storageVo = list.get(i);
            String lineName = storageVo.getLineName();
            if (StringUtils.isNull(lineName) || StringUtils.isNull(storageVo.getNameNorms()))
                continue;
            Double initial = storageVo.getInitial();//期初值
            Double adjustment = storageVo.getAdjustment();//期初调整值
            Double netWeight = storageVo.getNetWeight();//进料净重kg
            Double realExpend = storageVo.getRealExpend();//工控下料消耗值 kg
            Double dosage = storageVo.getDosage();//手动消耗值kg
            Double storeValue = initial + adjustment + netWeight - realExpend - dosage;
            if (map.containsKey(lineName)) {
                List<SysStorageVo> temp = map.get(lineName);
                if (storeValue.doubleValue() != 0)
                    storeValue = StringUtils.formatDouble(storeValue / 1000, 2);
                storageVo.setStoreValue(storeValue);
                storageVo.setRealExpend(realExpend + dosage);
                temp.add(storageVo);
                map.put(lineName, temp);
            } else {
                List<SysStorageVo> temp = new ArrayList<>();
                if (storeValue.doubleValue() != 0)
                    storeValue = StringUtils.formatDouble(storeValue / 1000, 2);
                storageVo.setStoreValue(storeValue);
                storageVo.setRealExpend(realExpend + dosage);
                temp.add(storageVo);
                map.put(lineName, temp);
            }
        }
        return map;
    }

    /**
     * 转换非共享仓得筒仓
     * @return
     */
    private List<SysStorageVo> convertEnjoy(List<SysStorageVo> list, Integer storageType) {
        Map<String, SysStorageVo> temp = new HashMap<>();
        for (int i = 0; i < list.size(); i++) {
            SysStorageVo storageVo = list.get(i);
            String lineName = storageVo.getLineName();
            Long materialId = storageVo.getMaterialId();
            Integer type = storageVo.getType();
            if (StringUtils.isNull(materialId) || StringUtils.isNull(type)
                    || type.intValue() != storageType)
                continue;//非筒仓
            String key = storageVo.getStorageId() + "_" + materialId;
            if (storageType.intValue() == MaterialStoreTypeEnum.DC.getCode().intValue())
                key = "" + materialId;
            Double netWeight = StringUtils.convertDouble(storageVo.getNetWeight());//进料净重kg
            Double realExpend = StringUtils.convertDouble(storageVo.getRealExpend());//工控下料消耗值 kg
            Double dosage = StringUtils.convertDouble(storageVo.getDosage());//手动消耗值kg
            if (temp.containsKey(key)) {
                SysStorageVo storageVo1 = temp.get(key);
//                storageVo1.setNetWeight(storageVo1.getNetWeight());
                storageVo1.setDosage(storageVo1.getDosage() + dosage);
                storageVo1.setRealExpend(storageVo1.getRealExpend() + realExpend);
                temp.put(key, storageVo1);
            } else {
                storageVo.setNetWeight(netWeight);
                storageVo.setDosage(dosage);
                storageVo.setRealExpend(realExpend);
                temp.put(key, storageVo);
            }
        }
        List<SysStorageVo> resultList = new ArrayList<>();
        for (String key : temp.keySet()) {
            SysStorageVo storageVo = temp.get(key);
            Double initial = storageVo.getInitial();//期初值
            Double adjustment = storageVo.getAdjustment();//期初调整值
            Double netWeight = storageVo.getNetWeight();//进料净重kg
            Double realExpend = storageVo.getRealExpend();//工控下料消耗值 kg
            Double dosage = storageVo.getDosage();//手动消耗值kg
            Double storeValue = initial + adjustment + netWeight - realExpend - dosage;
            if (storageVo.getName().indexOf("2-6") > -1) {
                System.out.println(111);
            }
            if (storeValue.doubleValue() != 0)
                storeValue = StringUtils.formatDouble(storeValue / 1000, 2);
            storageVo.setRealExpend(realExpend + dosage);
            storageVo.setStoreValue(storeValue);
            if (!StringUtils.isNull(storageVo.getMaxCapacity()) && storageVo.getMaxCapacity().doubleValue() > 100000000)
                storageVo.setMaxCapacity(100000000.0);
            resultList.add(storageVo);
        }
        return resultList;
    }
    /**
     * 转换非共享仓得筒仓
     * @return
     */
    private List<SysStorageVo> convertEnjoyDetail(List<SysStorageVo> list, Integer storageType) {
        Map<String, SysStorageVo> temp = new HashMap<>();
        for (int i = 0; i < list.size(); i++) {
            SysStorageVo storageVo = list.get(i);
            String lineName = storageVo.getLineName();
            Long materialId = storageVo.getMaterialId();
            Integer type = storageVo.getType();
            if (StringUtils.isNull(materialId) || StringUtils.isNull(type)
                    || type.intValue() != storageType)
                continue;//非筒仓
            String key = storageVo.getStorageId() + "_" + materialId;
//            if (storageType.intValue() == MaterialStoreTypeEnum.DC.getCode().intValue())
//                key = "" + materialId;
            Double netWeight = StringUtils.convertDouble(storageVo.getNetWeight());//进料净重kg
            Double realExpend = StringUtils.convertDouble(storageVo.getRealExpend());//工控下料消耗值 kg
            Double dosage = StringUtils.convertDouble(storageVo.getDosage());//手动消耗值kg
            if (temp.containsKey(key)) {
                SysStorageVo storageVo1 = temp.get(key);
                storageVo1.setNetWeight(storageVo1.getNetWeight() + netWeight);
                storageVo1.setDosage(storageVo1.getDosage() + dosage);
                storageVo1.setRealExpend(storageVo1.getRealExpend() + realExpend);
                temp.put(key, storageVo);
            } else {
                storageVo.setNetWeight(netWeight);
                storageVo.setDosage(dosage);
                storageVo.setRealExpend(realExpend);
                temp.put(key, storageVo);
            }
        }
        List<SysStorageVo> resultList = new ArrayList<>();
        for (String key : temp.keySet()) {
            SysStorageVo storageVo = temp.get(key);
            Double initial = storageVo.getInitial();//期初值
            Double adjustment = storageVo.getAdjustment();//期初调整值
            Double netWeight = storageVo.getNetWeight();//进料净重kg
            Double realExpend = storageVo.getRealExpend();//工控下料消耗值 kg
            Double dosage = storageVo.getDosage();//手动消耗值kg
            Double storeValue = initial + adjustment + netWeight - realExpend - dosage;
            if (storeValue.doubleValue() != 0)
                storeValue = StringUtils.formatDouble(storeValue / 1000, 2);
            storageVo.setRealExpend(realExpend + dosage);
            storageVo.setStoreValue(storeValue);
            resultList.add(storageVo);
        }
        return resultList;
    }
}
